﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using OpenTK;
using OpenTK.Input;
using OpenTK.Graphics;
using System.Runtime.InteropServices;

#if EMBEDDED
    using OpenTK.Graphics.ES20;
#else
using OpenTK.Graphics.OpenGL;
#endif

namespace MonoSettlers.RenderSystem
{
    public partial class GLRenderer : IRenderSystem
    {
        /// <summary>
        /// See <see cref="DrawSprite"/>.
        /// </summary>
        public int DrawSprite(IRenderableVisual inVisualOrNull, double inLeft, double inTop, double inWidth, double inHeight)
        {
            return DrawSprite(inVisualOrNull, (float)inLeft, (float)inTop, (float)inWidth, (float)inHeight);
        }

        /// <summary>
        /// Same as <see cref="DrawSprite"/> with last three parameters set to 255 (white). 
        /// </summary>
        public int DrawSprite(IRenderableVisual inVisualOrNull, float inLeft, float inTop, float inWidth, float inHeight)
        {
            return DrawSprite(inVisualOrNull, inLeft, inTop, inWidth, inHeight, 255, 255, 255);
        }

        /// <summary>
        /// Currently this method is incompatible to OpenGL ES 2.0. It will draw a sprite and also
        /// makes it available for object selection. In contrast to other overloads, it additionally
        /// provides the capability to "colorize" the sprite by mixing texels and vertex colors. Later, this
        /// allows us for an important eye candy via perlin noise, giving the scene a more natural look
        /// and feel.
        /// </summary>
        /// <param name="inVisualOrNull">Can be null, if sprite should not be selectable. If set, this is the value passed to <see cref="GLRenderer.MouseEnter"/>.</param>
        /// <param name="inLeft">X-Coordinate of the upper left corner in screen space coordinates.</param>
        /// <param name="inTop">Y-Coordinate of the upper left corner in screen space coordinates.</param>
        /// <param name="inWidth">Sprite width in screen coordinates.</param>
        /// <param name="inHeight">Sprite height in screen coordinates.</param>
        /// <param name="inRed">Red channel value for color mixing.</param>
        /// <param name="inGreen">Green channel value for color mixing.</param>
        /// <param name="inBlue">Blue channel value for color mixing.</param>
        /// <returns></returns>
        public int DrawSprite(IRenderableVisual inVisualOrNull, float inLeft, float inTop, float inWidth, float inHeight, byte inRed, byte inGreen, byte inBlue)
        {
            int selectionIndex = -1;

            if (IsSelectionPass && (inVisualOrNull != null))
            {
                m_SelectionPassResults.Add(inVisualOrNull);

                selectionIndex = m_SelectionPassResults.Count * SelectionGranularity;
                inRed = (byte)((selectionIndex & 0xFF));
                inGreen = (byte)((selectionIndex & 0xFF00) >> 8);
                inBlue = (byte)((selectionIndex & 0xFF0000) >> 16);
            }

            // TODO: Currently the following is the only point being incompatible to EMBEDDED compilation
            GL.Begin(BeginMode.Quads);
            {
                GL.Color3(inRed, inGreen, inBlue);

                GL.TexCoord2(0.0, 0.0);
                GL.Vertex3(inLeft, inTop, 0);
                GL.TexCoord2(1.0, 0.0);
                GL.Vertex3(inLeft + inWidth, inTop, 0);
                GL.TexCoord2(1.0, 1.0);
                GL.Vertex3(inLeft + inWidth, inTop + inHeight, 0);
                GL.TexCoord2(0.0, 1.0);
                GL.Vertex3(inLeft, inTop + inHeight, 0);
            }
            GL.End();

            GLRenderer.CheckError();

            if (selectionIndex < 0)
                return -1;
            else
                return m_SelectionPassResults.Count - 1;
        }
    }
}
